package com.spring.boot.core.message;

import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.spring.boot.core.common.SharedTimer;

public class MessageSystem {
	private static final Logger logger = LoggerFactory.getLogger(MessageSystem.class);
	// 重连次数
	private static final int DEFAULT_RETRY_TIMES = 3;
	private static final long SCHEDULT_INTERVAL = 1 * 1000L;

	private static final Map<MessageType, MessageListener> listenersMap = Maps.newHashMap();

	private static List<Message> msgList = Lists.newArrayList();
	private static final ReentrantLock lock = new ReentrantLock();

	private MessageSystem() {
	}

	static {
		SharedTimer.schedule(new Runnable() {

			@Override
			public void run() {
				List<Message> msgList = getMsgList();
				while (!msgList.isEmpty()) {
					handleMessage(msgList.remove(0));
				}
			}

		}, 0, SCHEDULT_INTERVAL);
	}

	public static synchronized void registerMessageListener(MessageType type, MessageListener listener) {
		if (listenersMap.containsKey(type)) {
			logger.warn("注册消息错误,含有重复的类型:" + type.toString());
			return;
		}
		listenersMap.put(type, listener);
	}

	private static void handleMessage(Message message) {
		MessageListener listener = listenersMap.get(message.getType());
		if (listener != null) {
			boolean retry = false;
			try {
				listener.onMessage(message);
			} catch (Throwable t) {
				retry = true;
				logger.error(String.format("Exception occurs during handler message %s", new Object[] { message }), t);
			}
			if (retry) {
				handlerRetryable(message, listener);
			}
		}

	}

	private static void handlerRetryable(Message message, MessageListener listener) {
		if (!listener.retryable()) {
			return;
		}
		boolean fail = false;

		for (int i = 0; i < DEFAULT_RETRY_TIMES; i++) {
			fail = false;
			try {
				listener.onMessage(message);
			} catch (Throwable t) {
				fail = true;
				logger.error(String.format("Exception occurs during listener %s handler message %s", new Object[] { listener, message }), t);
			}
			if (!fail) {
				// 处理成功,结束循环
				break;
			}
		}
	}

	private static final List<Message> getMsgList() {
		lock.lock();
		List<Message> msg = msgList;
		msgList = Lists.newArrayList();
		lock.unlock();
		return msg;
	}

	public static final void createMessage(MessageType type, Object data) {
		MessageImpl msg = new MessageImpl();
		msg.setType(type);
		msg.setObject(data);
		lock.lock();
		msgList.add(msg);
		lock.unlock();
	}

}
